//
//  SCEmoticonPackage.swift
//  表情键盘
//
//  Created by newuser on 15/12/28.
//  Copyright © 2015年 newuser. All rights reserved.
//

import UIKit

class SCEmoticonPackage: NSObject {

    /// id表情包的文件夹名称
    var id: String
    
    /// 表情包的名称
    var group_name_cn: String?
    
    /// 所有的表情模型
    var emoticons: [CZEmociton] = [CZEmociton]()
    
    /// 表情包构造函数
    init(id: String) {
        self.id = id
        super.init()
    }
    
    // 获取 Emoticons.bundle 的路径 直接查找
    static let bundlePath = NSBundle.mainBundle().pathForResource("Emoticons", ofType: "bundle")!
    
    ///让表情包只加载一次
    static let packages = SCEmoticonPackage.loadPackages()
    
    
    /// 加载所有的表情包模型
    private class func loadPackages() -> [SCEmoticonPackage]? {
        //  加载到emoticons.plist,可以知道有每个表情包的文件夹名称
        
        //拼接emoticons.plist的路径 bundlePath/emoticons.plist
        let plistPath = (bundlePath as NSString).stringByAppendingPathComponent("emoticons.plist")
        
        //读取emoticons.plist里面的每个表情包文件夹名称
        let emoticonDict = NSDictionary(contentsOfFile: plistPath)!
        
        //  获取packages所对应的value是一个数组,数组里面存放的是字典
        if let array = emoticonDict["packages"] as? [[String: AnyObject]] {
            // 定义数组保存表情包模型
            var packages = [SCEmoticonPackage]()
            
            
            //创建最近表情
            let recentPackage = SCEmoticonPackage(id: "")

            recentPackage.group_name_cn = "最近"
            
            //将表情包添加到数组最前面
            packages.append(recentPackage)
            //添加删除空白按钮
            recentPackage.appendEmptyEmoticon()
            
            
            //  遍历数组里面的元素
            for dict in array {
                let id = dict["id"] as! String
                //  创建表情包
                let package = SCEmoticonPackage(id: id)
                
                // 表情包加载表情
                package.loadEmoticon()
                
                packages.append(package)
            }
            
            // 返回所有的表情包模型
            return packages
        }
        
        return nil
    }
    
    /// 加载所有的表情,加载表情包的名称
    func loadEmoticon() {
        // info.plist全路径
        let infoPlistPath = ((SCEmoticonPackage.bundlePath as NSString).stringByAppendingPathComponent(id) as NSString).stringByAppendingPathComponent("info.plist")
        
        // 加载数据
        let infoDict = NSDictionary(contentsOfFile: infoPlistPath)!
        
        //获取表情包名称
        group_name_cn = infoDict["group_name_cn"] as? String
        
        // 获取表情模型数组
        if let emoticonsArray = infoDict["emoticons"] as? [[String: AnyObject]] {
           
            var index = 0
            
            // 遍历获取每一个表情对应的字典
            for dict in emoticonsArray {
                // 字典转模型,传入表情包文件夹名称id
                let emoticon = CZEmociton(id: id, dict: dict)
                
                // 将表情模型添加到表情模型数组里面
                emoticons.append(emoticon)
                index++
                
                //最后一个显示删除
                if index == 20 {
                emoticons.append(CZEmociton(removeEmoticon: true))
                    index = 0
                }
            }
        }
        appendEmptyEmoticon()
    }

    
    func appendEmptyEmoticon() {
        let count = emoticons.count % 21
        
        if count > 0 || emoticons.count == 0 {
        
            for _ in count..<20 {
            //创建空白按钮
            emoticons.append(CZEmociton(removeEmoticon: false))
            }
            //添加删除按钮
            emoticons.append(CZEmociton(removeEmoticon: true))
        }
    }
    
    
    //TODO: 有问题
    //MARK: - 添加表情模型到最近表情包
    class func addFavorateEmoticon(emoticon: CZEmociton) {
    
        if emoticon.removeEmoticon {
           return
        }
        
        if emoticon.pngPath == nil && emoticon.emoji == nil {
          return
        }
        
        emoticon.times++
        //获取到最近表情包模型里面所有模型
        var recentEmoticons = packages![0].emoticons
        
        //将删除按钮移除数组,不参加排序
        let removeEmoticon = recentEmoticons.removeLast()
        
       // contains判断数组中是否存在某个元素
        let contains = recentEmoticons.contains(emoticon)
        
        if !contains{
        
            recentEmoticons.append(emoticon)
        }
          //数组排序,需要重新赋值
        recentEmoticons = recentEmoticons.sort({ (e1, e2) -> Bool in
            
            return e1.times > e2.times
        })
        
        //删除保证最近表情包里面的表情数量固定
        if !contains {
        
            recentEmoticons.removeLast()
        }
        //将删除按钮添加回来
        recentEmoticons.append(removeEmoticon)
        print("添加后的最近表情包:\(recentEmoticons.count),\(recentEmoticons)")
       
    
        packages![0].emoticons = recentEmoticons
    }
    
    
    // 对象的打印
    override var description: String {
     
        return "\n\t表情包模型: id:\(id), group_name_cn: \(group_name_cn), emoticons: \(emoticons))"
    }
}

/// 表情模型
class CZEmociton: NSObject {
    /// id 表情包文件夹名称
    var id: String?
    
    /// 表情名称,用于网络传输
    var chs: String?
    
    /// 表情图片名称
    var png: String? {
        didSet {
            // 当kvc设置png时,来拼接完整地图片路径
            // 完整地图片路径 = bundlePath + id + 图片名称
            pngPath = SCEmoticonPackage.bundlePath + "/\(id!)/\(png!)"
        }
    }
    
    /// 表情图片的完整路径
    var pngPath: String?
    
    /// code用于显示emoji表情
    var code: String? {
        didSet {
        
            let scanner = NSScanner(string: code!)
            
            var result: UInt32 = 0
            scanner.scanHexInt(&result)
            let scalar = UnicodeScalar(result)
            
            let c = Character(scalar)
            emoji = String(c)
        }
    
    }
    
    var emoji: String?

    /// 表情的使用次数,使用次数多的会显示在最近表情包的最前面
    var times = 0
    
    ///true 是删除按钮 ,false 是空白按钮
    var removeEmoticon = false
    /// 模型显示删除按钮和空白表情,true 是删除按钮, false 是空白按钮
    init(removeEmoticon:Bool)
    {
        self.removeEmoticon = removeEmoticon
        super.init()
    }
    
    
    /// 字典转模型
    init(id: String?, dict: [String: AnyObject]) {
        super.init()
        
        self.id = id
        // 使用KVC赋值
        setValuesForKeysWithDictionary(dict)
    }
    
    // 字典的key在模型中找不到对应的属性
    override func setValue(value: AnyObject?, forUndefinedKey key: String) {}
    
    // 对象打印方法
    override var description: String {
        return "\n\t\t表情模型:chs: \(chs), png: \(png), code: \(code), removeEmoticon:\(removeEmoticon), times: \(times)"
    }
    
    /**
     将表情模型转换成带图片的属性文本
     
     - parameter font: font
     
     - returns: 带图片的属性文本
     */
    func emoticonToAttrString(font: UIFont) -> NSAttributedString {
        // 判断是否有图片
        if let pngP = self.pngPath {
            // 图片路径有值
            // 2.1创建附件
            let attachment = SCTextAttachment()
            
            // 2.2给附件添加图片
            attachment.image = UIImage(contentsOfFile: pngP)
            
            // 2.2.1设置附件的图片名称
            attachment.chs = chs
            
            // 2.2.2设置图片的bounds
            let w = font.lineHeight
            attachment.bounds = CGRect(x: 0, y: -(w * 0.2), width: w, height: w)
            
            // 2.3将附件转成可变的属性文本
            let attrText = NSMutableAttributedString(attributedString: NSAttributedString(attachment: attachment))
            
            // 2.3.2发现在图片后面连续添加图片,图片会变小.原因是附件缺少Font属性,给附件添加Font属性
            attrText.addAttribute(NSFontAttributeName, value: font, range: NSRange(location: 0, length: 1))
            
            return attrText
        } else {
            return NSAttributedString(string: "")
        }
    }
    
    /**
     根据表情名称找到对应的表情模型
     
     - parameter name: 表情名称
     
     - returns: 找到的表情模型
     */
    class func emoticonNameToEmoticon(name: String) -> CZEmociton? {
        
        // 记录下找到的模型
        var emoticon: CZEmociton?
        // 遍历所有的表情包
        for package in SCEmoticonPackage.packages! {
            // 查找每个表情包里面所有模型,如果找到模型名称和name一样的就说明找到了对应的模型
            let array = package.emoticons.filter({ (emoticon) -> Bool in
                // true表示匹配到的数据
                return emoticon.chs == name
            })
            
            // 获取过滤后的数组中的第一个元素array里面可能没有元素
            let e = array.first
            
            if e != nil {
                // 说明在当前这个表情包里面找到了对应的表情模型
                emoticon = e
                
                // 注意: 一定要跳出循环
                break
            }
        }
        
        // 返回表情模型,有可能有,也有可能没有
        return emoticon
    }
    
    /*
    1.从微博内容中截取表情名称
    2.根据表情名称找到对应的表情模型 *
    3.将表情模型转成带表情图片的属性文本 *
    4.将微博内容中的表情名称替换成 带表情图片的属性文本
    */
    /// 将微博内容中的表情名称替换成表情图片
    class func stringToEmoticonText(text: String) -> NSAttributedString {
        // 1.从微博内容中截取表情名称
        // 定义查找规则,在正则表达式中[ ] 是有特殊含义的,需要转义
        let pattern = "\\[.*?\\]"
        
        // 创建正则表达式对象
        let regular = try! NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.DotMatchesLineSeparators)
        
        // 使用正则表达式来匹配字符串
        let results = regular.matchesInString(text, options: NSMatchingOptions(rawValue: 0), range: NSRange(location: 0, length: text.characters.count))
        
        // 获取匹配的结果数
        var count = results.count   // 4: 3,2,1
        
        // 普通的文本是不能替换属性文本的, 将传入的微博内容整个转成属性文本
        let attrText = NSMutableAttributedString(string: text)
        
        // 从后面开始替换
        while count > 0 {
            count--
            // 获取对应的结果
            let result = results[count]
            
            // 获取结果里面匹配到的范围
            //            let number = result.numberOfRanges
            
            // 获取到结果中匹配的范围
            let range = result.rangeAtIndex(0)
            
            // 截取表情名称
            let emoticonName = (text as NSString).substringWithRange(range)
            print("表情名称: \(emoticonName)")
            
            // 2.根据表情名称找到对应的表情模型 *
            if let emoticon = CZEmociton.emoticonNameToEmoticon(emoticonName) {
                // 3.将表情模型转成带表情图片的属性文本 *
                let attr = emoticon.emoticonToAttrString(UIFont.systemFontOfSize(14))
                
                // 4.将微博内容中的表情名称替换成 带表情图片的属性文本
                attrText.replaceCharactersInRange(range, withAttributedString: attr)
            }
        }
        
        // 微博里面的所有表情名称都替换好了
        return attrText
    }
}
